package Team.Yaohuo.controller;

import Team.Yaohuo.properties.JwtProperties;
import Team.Yaohuo.utils.MegPushUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Date;

@Configuration
@ConfigurationProperties(prefix = "sso")
@NoArgsConstructor
@AllArgsConstructor
@Validated
class SSOConfig {
    @Getter
    @Setter
    private String acs;
    @Getter
    @Setter
    private String issuer;
    @Getter
    @Setter
    private String username;
    @Getter
    @Setter
    private String secret;
}

@Service
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
class SSOService {
    @Getter
    @Setter
    @Autowired
    private SSOConfig ssoConfig;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private HttpServletRequest httpServletRequest;
    @Autowired
    private MegPushUtil messagePushUtil;
    public String getResponse(String request){

        log.info("sso获取到的request的jwt为:{}", request);

        Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecret());
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT decoded = verifier.verify(request);
        if (!"sso_req".equals(decoded.getClaim("type").asString())) {
            return "";
        }
        HttpSession session = httpServletRequest.getSession();
        String userId=(String) session.getAttribute("userId");
        log.info("当前sso获取到的userId为:{}", userId);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.HOUR_OF_DAY, 2);
        // 开启消息推送
        messagePushUtil.yxMes(userId, (String) session.getAttribute("access_token"));

        return JWT.create()
                .withClaim("type", "sso_res")
                .withClaim("username", userId)
//                .withIssuer(this.ssoConfig.getIssuer())
                .withAudience("com.jiandaoyun")
                .withExpiresAt(calendar.getTime())
                .withIssuedAt(new Date(System.currentTimeMillis()))
                .sign(algorithm);
    }
}

@Controller
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
class SSOController {
    @Getter
    @Setter
    @Autowired
    private SSOConfig ssoConfig;

    @Getter
    @Setter
    @Autowired
    private SSOService ssoService;
    @Autowired
    private HttpServletRequest httpServletRequest;

    @GetMapping("/sso")
    void authn(
            @RequestParam(name = "request", defaultValue = "") String request,
            @RequestParam(name = "state", defaultValue = "") String state,
            HttpServletResponse httpServletResponse
    ) throws IOException {
        HttpSession session = httpServletRequest.getSession();
        log.info("当前sso请求requset为:{}", request);
        String response = this.ssoService.getResponse(request);
        log.warn("sso重定向响应的地址为:{}", String.format(
                "%s?response=%s&state=%s",
                this.ssoConfig.getAcs(), response, state
        ));
        String url = (String) session.getAttribute("url");
        log.info("sso接收到的url为:{}", url);
        if (url != null) {
            httpServletResponse.sendRedirect(
                    String.format(
                            "%s?response=%s&state=%s&redirect_uri=%s",
                            this.ssoConfig.getAcs(), response, state, URLEncoder.encode(url)
                    )
            );
        }else {
            httpServletResponse.sendRedirect(
                    String.format(
                            "%s?response=%s&state=%s",
                            this.ssoConfig.getAcs(), response, state
                    )
            );
        }
    }
}